/**
 * 
 */
package com.app.framework.http;

import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.util.zip.GZIPOutputStream;

import org.apache.log4j.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpResponseStatus;
import org.jboss.netty.handler.codec.http.HttpVersion;

import com.app.framework.context.Request;
import com.app.framework.context.Response;
import com.app.framework.handler.GameUpstreamHandler;
import com.app.framework.result.RequestResult;
import com.app.framework.util.JSONUtil;
import com.app.framework.util.StringUtils;

/**
 * @author lisong
 * @version 2013-3-4 下午3:27:30
 */
public class HttpResponse extends DefaultHttpResponse implements Response<Serializable>  {

	private static final Logger logger = Logger.getLogger(HttpResponse.class);
	
	private RequestResult<Serializable> result;
	
	private Channel channel;
	
	private Request request;
	
	private String sessionId;
	
	private int requestId;

	
	/**
	 * @param version
	 * @param status
	 */
	public HttpResponse(HttpVersion version, HttpResponseStatus status,Channel channel) {
		super(version, status);
		this.channel = channel;
	}

	@Override
	public void output() throws Exception {
		
		if(result != null) {
		
			String responseJson = JSONUtil.toJSON(result.asResult());
			
			ByteArrayOutputStream out = new ByteArrayOutputStream();  
		    
			GZIPOutputStream gzip = new GZIPOutputStream(out);
		    
			gzip.write(responseJson.getBytes(RESPONSE_CHARSET));
		    
			out.close();
		    
			gzip.close();
		    
			byte[] bytes = out.toByteArray();
			
			if(sessionId != null) {
				
				addHeader(GameUpstreamHandler.REQUEST_SESSIONID_STRING, sessionId);
			}
			
			addHeader(GameUpstreamHandler.REQUEST_ID_STRING, requestId);
			
			ChannelBuffer content = ChannelBuffers.dynamicBuffer();

			content.writeBytes(bytes);
			
			setContent(content);
			
			write();
			
		}
	}
	
	private void write() {
		ChannelFuture future = channel.write(this);
		future.addListener(ChannelFutureListener.CLOSE);
		future.addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
	}

	@Override
	public void close() {

		request = null;
		
		result = null;
		
		channel = null;
	}

	@Override
	public void setRequestResult(RequestResult<Serializable> result) {
		this.result = result;
		
	}

	@Override
	public RequestResult<Serializable> getRequestResult() {
		return result;
	}

	public Request getRequest() {
		return request;
	}

	public void setRequest(Request request) {
		this.request = request;
	}

	public void setSessionId(String sessionId) {
		this.sessionId = sessionId;
	}

	public void setRequestId(int requestId) {
		this.requestId = requestId;
	}

	@Override
	public void protocolException(int code, Serializable message) {
		
		try {
			String msg = message.toString();
			
			if(StringUtils.isNullOrEmpty(msg)) {
				
				message = "unknown error";
				
			}
			if(code <= 0) {
				
				code = 500;
				
			}
			
			HttpResponseStatus status = new HttpResponseStatus(code,msg);
			
			setStatus(status);
			
			ChannelBuffer content = ChannelBuffers.dynamicBuffer();
			
			content.writeBytes(msg.getBytes(RESPONSE_CHARSET));
			
			setContent(content);
			
			write();
			
			close();
			
		} catch (Exception e) {
			
			e.printStackTrace();
			
			logger.error(message,e);
		}
	}
	
}
